<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
  <style>
  .box {
    padding: 20px;
  }
  .box label {
    display: block;
  }
  #result {
    padding: 10px;
    font-size: 21px;
    font-weight: 700;
  }
  </style>
  <title>检测 Turn 服务是否可用</title>
</head>
<body>
  <div class="box">
    <label>URL: <input type="text" name="url"></label>
    <label>credential: <input type="text" name="credential"></label>
    <label>username: <input type="text" name="username"></label>
    <button id="check-btn">检测</button>
  </div>
  <div id="result"></div>

  <script>
    function checkTURNServer(turnConfig, timeout){ 
      return new Promise(function(resolve, reject){
        setTimeout(function(){
            if(promiseResolved) return;
            resolve(false);
            promiseResolved = true;
        }, timeout || 5000);

        var promiseResolved = false
          , myPeerConnection = window.RTCPeerConnection || window.mozRTCPeerConnection || window.webkitRTCPeerConnection   //compatibility for firefox and chrome
          , pc = new myPeerConnection({iceServers:[turnConfig]})
          , noop = function(){};
        pc.createDataChannel("");    //create a bogus data channel
        pc.createOffer(function(sdp){
          if(sdp.sdp.indexOf('typ relay') > -1){ // sometimes sdp contains the ice candidates...
            promiseResolved = true;
            resolve(true);
          }
          pc.setLocalDescription(sdp, noop, noop);
        }, noop);    // create offer and set local description
        pc.onicecandidate = function(ice){  //listen for candidate events
          if(promiseResolved || !ice || !ice.candidate || !ice.candidate.candidate || !(ice.candidate.candidate.indexOf('typ relay')>-1))  return;
          promiseResolved = true;
          resolve(true);
        };
      });   
    }
  
    const $url = $('.box input[name=url]');
    const $credential = $('.box input[name=credential]');
    const $username = $('.box input[name=username]');
    const $result = $('#result');
  
    $('#check-btn').on('click', () => {
      console.log('开始检测...');
      $result.text('检测中...');
      checkTURNServer({
          url: $url.val(),
          username: $credential.val(),
          credential: $username.val()
      }).then(bool => {
          console.log('is TURN server active? ', bool? 'yes':'no');
          $result.text(bool ? '正常' : '失效');
      }).catch(error => {
          $result.text(error);
      });
    });

  </script>
</body>
</html>